﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Moq;
using System.IO;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using MvcApi;

namespace Unit_Tests
{
    public static class MockHelpers
    {
        public static Mock<ActionExecutedContext> ActionExecutedContext(string[] acceptTypes, Mock<ControllerContext> controllerContext)
        {            
            var controller = new Mock<ControllerBase>();
            controller.Object.ViewData.Model = SimpleModel.Create();
            controller.Object.ControllerContext = controllerContext.Object;
            
            var result = new Mock<ActionExecutedContext>();
            result.SetupGet(c => c.HttpContext.Request.AcceptTypes).Returns(acceptTypes);
            result.SetupGet(c => c.Controller).Returns(controller.Object);
            
            return result;
        }

        public static Mock<ActionExecutingContext> ActionExecutingContext(string contentType, object primitive = null, bool useApiBindOnModel = false)
        {
            var modelParameter = new Mock<ParameterDescriptor>();
            modelParameter.SetupGet(p => p.ParameterName).Returns("model");
            modelParameter.SetupGet(p => p.ParameterType).Returns(typeof(SimpleModel));
            if (useApiBindOnModel) modelParameter.Setup(p => p.GetCustomAttributes(typeof (ApiBind), false)).Returns(new[] { new ApiBind() });

            var actionParameters = new Dictionary<string, object>() { { "model", null } };
            var parameterDiscriptors = new List<ParameterDescriptor>() { modelParameter.Object };

            if (primitive != null)
            {
                var primitiveParameter = new Mock<ParameterDescriptor>();
                primitiveParameter.SetupGet(p => p.ParameterName).Returns("primitive");
                primitiveParameter.SetupGet(p => p.ParameterType).Returns(primitive.GetType());

                actionParameters.Add("primitive", primitive);
                parameterDiscriptors.Add(primitiveParameter.Object);
            }

            var result = new Mock<ActionExecutingContext>();

            result.SetupGet(r => r.ActionParameters).Returns(actionParameters);
            result.SetupGet(r => r.HttpContext.Request.ContentType).Returns(contentType);
            result.Setup(r => r.ActionDescriptor.GetParameters()).Returns(parameterDiscriptors.ToArray());

            return result;
        }

        public static string ToJson(this object @object)
        {
            return (new JavaScriptSerializer()).Serialize(@object);
        }

        public static string ToXml(this object @object)
        {
            var builder = new StringBuilder();

            using (var writer = new StringWriter(builder))
                (new XmlSerializer(@object.GetType())).Serialize(writer, @object);

            return builder.ToString();
        }
    }
}
